package lintulaskenta.validointi;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lintulaskenta.entity.Havainnointitapahtuma;
import lintulaskenta.entity.Reitti;
import lintulaskenta.rekisteri.ReittiRekisteri;
import lintulaskenta.pulautin.Havainnointikokonaisuus;

//@author jjnyman & Pajunen
public class validointiKirjasto {

    public validointiKirjasto() {
    }

     /*
      * Tarkistaa onko kaikissa lisättävissä havainnointitapahtumissa sama havainnoijanumero. Palauttaa false jos ei.
      * Käytännössä siis pulautinfunkkari, sillä kantaan ei kosketa.
      */

    public boolean tarkistaOnkoSamaHavainnoijaNro(Havainnointikokonaisuus hk){
        int havainnoijaNro = hk.getHavainnointitapahtumat().get(0).getHavainnoijaNumero();
        for(Havainnointitapahtuma ht : hk.getHavainnointitapahtumat()){
            if(ht.getHavainnoijaNumero() != havainnoijaNro){
                return false;
            }
        }
        return true;
    }




    /*
     * Dumbass testi joka vain kokeilee onko parven koko jonkun järkevän määrän
     * sisällä. Esim. jos väitetään että parvi kohdattiin jonka koko on
     * 30kk, niin huomautellaan asiasta
     */
    public boolean tarkistaParvenKoko(int parvenKoko) {
        if (parvenKoko > 1000) {
            return false;
        }
        return true;
    }

    /*
     * Simppeli metodi joka tarkistaa onko säde muuta kuin 50 tai 25m
     */
    public boolean tarkistaSade(int sade) {
        if (sade != 50 || sade != 25) {
            return false;
        }
        return true;
    }

    /* Ohjeiden mukaan laskenta tulisi suorittaa ennen kello 10 aamulla
     * joten vingutaan jos tuntuu menevän liian myöhäiseksi.
     * Ei kannata tehdä tarkaksi ehdoksi, mutta tarkistusfunkkari joka
     * voi huomauttaa asiasta.
     */
    public boolean herjaaLopetusajasta(int[] aika) {
        int lopetustunti = aika[2];
        if (lopetustunti > 9) {
            return false;
        } else {
            return true;
        }
    }

    //TietokannanKasittelija dbkasittelija = new TietokannanKasittelija();
    /***************************************************************************************
     *                                                                                    *
     * Kaksi eri funkkaria joilla kokeilla onko laskenta-aika uudessa havaintotapahtumassa*
     * hyväksyttävät ajankohdat ensimmäisen laskennan kannalta.                           *
     *                                                                                    *
     * Ensin kannattaa ajaa kaykoLaskentaPvm() ja jos se menee läpi, niin sitten tarkan   *
     * kellonajan tarkistus kaykoLaskentaAika(). Eri metodit, jotta voidaan myöhemmin     *
     * käyttää jäljittämiseen, että mikä oli vikana, eikä vain ilmoittaa geneerista failia*
     *                                                                                    *
     **************************************************************************************/
    /*
     * Hakee tällä hetkellä reitin havaintokerrat ja järjestää ne kronologiseen
     * järjestykseen niin että uusin [0]...[n] vanhin
     * Vielä pitää päättää  miten aika esitetään ja tyrkätä se parametrinä sisään
     * sekä tehdä sille vertailu tietyn havaintokerran/-kertojen välillä. Tällä hetkellä
     * tarkistaa onko ensimmäisen havaintotapahtuman ja kokeiltavan tapahtuman
     * tuntimäärän välillä eroa yli 30 min. Palauttaa true jos ei, jos taas yli
     * niin false.
     */
    public static boolean kaykoLaskentaAika(Reitti reitti, Havainnointitapahtuma tapahtuma) throws Exception {

        List<Havainnointitapahtuma> havainnot = jarjestaHavainnot(reitti);

        int vuosi = tapahtuma.getVuosi(), kuukausi = tapahtuma.getKuukausi(), minuutti = tapahtuma.getAlkuMinuutit();
        int tunti = tapahtuma.getAlkuTunnit(), paiva = tapahtuma.getPaiva();

        Havainnointitapahtuma ensimmainen = havainnot.get(havainnot.size() - 1);
        int erotus = 0;

        if (tunti == ensimmainen.getAlkuTunnit()) {
            erotus = Math.abs(minuutti - ensimmainen.getAlkuMinuutit());
            if (erotus > 30) {
                System.out.println("Ekan reitin aloitusaika: " + ensimmainen.getAlkuTunnit() + ":" + ensimmainen.getAlkuMinuutit());
                System.out.println("Verrattavan reitin aloitusaika: " + tunti + ":" + minuutti + "\nTuntierotus: " + erotus + " minuuttia");
                return false;
            }
            return true;
        } else if (tunti < ensimmainen.getAlkuTunnit()) {
            int tuntierotus = ensimmainen.getAlkuTunnit() - tunti;
            erotus = ((60 * (tuntierotus - 1)) + (60 - minuutti)) + ensimmainen.getAlkuMinuutit();
            if (erotus > 30) {
                System.out.println("Ekan reitin aloitusaika: " + ensimmainen.getAlkuTunnit() + ":" + ensimmainen.getAlkuMinuutit());
                System.out.println("Verrattavan reitin aloitusaika: " + tunti + ":" + minuutti + "\nTuntierotus: " + erotus + " minuuttia");
                return false;
            }
            return true;
        } else if (tunti > ensimmainen.getAlkuTunnit()) {
            int tuntierotus = tunti - ensimmainen.getAlkuTunnit();
            erotus = ((60 * (tuntierotus - 1)) + (60 - minuutti)) + minuutti;
            if (erotus > 30) {
                System.out.println("Ekan reitin aloitusaika: " + ensimmainen.getAlkuTunnit() + ":" + ensimmainen.getAlkuMinuutit());
                System.out.println("Verrattavan reitin aloitusaika: " + tunti + ":" + minuutti + "\nTuntierotus: " + erotus + " minuuttia");
                return false;
            }
            return true;
        }
        return false;
    }

    /*
     * Hakee tällä hetkellä reitin havaintokerrat ja järjestää ne kronologiseen
     * järjestykseen niin että uusin [0]...[n] vanhin
     * Vielä pitää päättää  miten aika esitetään ja tyrkätä se parametrinä sisään
     * sekä tehdä sille vertailu tietyn havaintokerran/-kertojen välillä. Tällä hetkellä
     * tarkistaa onko ensimmäisen havaintotapahtuman ja kokeiltavan tapahtuman päivämäärän
     * välillä eroa yli 7 vrk. Jos ei palauttaa true, muuten false
     */
    public static boolean kaykoLaskentaPvm(Reitti reitti, Havainnointitapahtuma tapahtuma) throws Exception {
        List<Havainnointitapahtuma> havainnot = jarjestaHavainnot(reitti);

        int vuosi = tapahtuma.getVuosi(), kuukausi = tapahtuma.getKuukausi(), minuutti = tapahtuma.getAlkuMinuutit();
        int tunti = tapahtuma.getAlkuTunnit(), paiva = tapahtuma.getPaiva();

        Havainnointitapahtuma ensimmainen = havainnot.get(havainnot.size() - 1);
        int erotus = 0;

        if (kuukausi == ensimmainen.getKuukausi()) {
            erotus = Math.abs(ensimmainen.getPaiva() - paiva);
            if (erotus > 7) {
                System.out.println("Reitin laskentapäivämäärissä on heittoa");
                System.out.println("Ensimmäisen reitin laskentapäivä: " + ensimmainen.getPaiva() + "." + ensimmainen.getKuukausi() + "." + ensimmainen.getVuosi());
                System.out.println("Verrattavan reitin laskentapäivä: " + paiva + "." + kuukausi + "." + vuosi + "\nErotus päivissä: " + erotus);
                return false;
            }
            return true;
        } else if (kuukausi < ensimmainen.getKuukausi()) {
            if (kuukausi == 5) {
                erotus = (31 - paiva) + ensimmainen.getPaiva();
                if (erotus > 7) {
                    System.out.println("Reitin laskentapäivämäärissä on heittoa");
                    System.out.println("Ensimmäisen reitin laskentapäivä: " + ensimmainen.getPaiva() + "." + ensimmainen.getKuukausi() + "." + ensimmainen.getVuosi());
                    System.out.println("Verrattavan reitin laskentapäivä: " + paiva + "." + kuukausi + "." + vuosi + "\nErotus päivissä: " + erotus);
                    return false;
                }
                return true;
            } else if (kuukausi == 6) {
                erotus = (30 - paiva) + ensimmainen.getPaiva();
                if (erotus > 7) {
                    System.out.println("Reitin laskentapäivämäärissä on heittoa");
                    System.out.println("Ensimmäisen reitin laskentapäivä: " + ensimmainen.getPaiva() + "." + ensimmainen.getKuukausi() + "." + ensimmainen.getVuosi());
                    System.out.println("Verrattavan reitin laskentapäivä: " + paiva + "." + kuukausi + "." + vuosi + "\nErotus päivissä: " + erotus);
                    return false;
                }
                return true;
            }
        } else if (kuukausi > ensimmainen.getKuukausi()) {
            if (kuukausi == 6) {
                erotus = (31 - ensimmainen.getPaiva()) + paiva;
                if (erotus > 7) {
                    System.out.println("Reitin laskentapäivämäärissä on heittoa");
                    System.out.println("Ensimmäisen reitin laskentapäivä: " + ensimmainen.getPaiva() + "." + ensimmainen.getKuukausi() + "." + ensimmainen.getVuosi());
                    System.out.println("Verrattavan reitin laskentapäivä: " + paiva + "." + kuukausi + "." + vuosi + "\nErotus päivissä: " + erotus);
                    return false;
                }
                return true;
            } else if (kuukausi == 7) {
                erotus = (30 - ensimmainen.getPaiva()) + paiva;
                if (erotus > 7) {
                    System.out.println("Reitin laskentapäivämäärissä on heittoa");
                    System.out.println("Ensimmäisen reitin laskentapäivä: " + ensimmainen.getPaiva() + "." + ensimmainen.getKuukausi() + "." + ensimmainen.getVuosi());
                    System.out.println("Verrattavan reitin laskentapäivä: " + paiva + "." + kuukausi + "." + vuosi + "\nErotus päivissä: " + erotus);
                    return false;
                }
                return true;
            }
        }
        return false;
    }

    /*
     *   Vertailufunkkari jotta haettavan Havaintotapahtumalistan saa sortattua.
     */
    private static final Comparator<Havainnointitapahtuma> Vuosijärjestys = new Comparator<Havainnointitapahtuma>() {

        public int compare(Havainnointitapahtuma h1, Havainnointitapahtuma h2) {
            Integer vuosi1 = new Integer(h1.getVuosi());
            Integer vuosi2 = new Integer(h2.getVuosi());
            return vuosi2.compareTo(vuosi1);
        }
    };

    /*
     * Epäoptimi tapa noukkia varmaankin, sillä varmasti tietokanta tukee hakua
     * jossa pyydetään jonkin reitin kaikki havaintotiedot. Voi olla myös iloa
     * mikäli halutaan esim. laskea keskiarvoa tjsp. eikä vain yhtä havaintotapahtumaa
     */
    public static List<Havainnointitapahtuma> jarjestaHavainnot(Reitti reitti) throws Exception {

        List<Havainnointitapahtuma> havainnot = new ArrayList<Havainnointitapahtuma>();
        for (Havainnointitapahtuma havainto : reitti.getHavainnointitapahtumat()) {
            havainnot.add(havainto);
        }
        Collections.sort(havainnot, Vuosijärjestys);
//            for (Havainnointitapahtuma h : havainnot) {
//                System.out.println(h.getVuosi());
//            }
        return havainnot;
    }
}
